Skip to content

Combined fixes from contributor PRs 269, 272-276 - #286

Merged
pk910 merged 8 commits into
masterfrom
pk910/combined-fixes
Sep 11, 2026
Merged

pk910 merged 8 commits into
masterfrom
pk910/combined-fixes

Conversation

@pk910

@pk910 pk910 commented Sep 11, 2026

Copy link
Copy Markdown
Member

Summary

Combined fix branch re-implementing the useful parts of the externally contributed PRs #269, #272, #273, #274, #275 and #276 on top of the current txtypes-based master. Each PR describes a real bug in master; the fixes here were re-derived from the current code rather than rebased, and the tests exercise the real code paths instead of mirroring them.

Fixes #260.

Changes

erc20_bloater approach

#269 raises the per-tx gas above 16.7M to obtain a state-gas reservoir. That is rejected outright on Osaka chains that have not activated Amsterdam yet, which the PR compensates with string matching on gas limit too high and a per-round fallback. It also sizes each tx to almost the full block gas limit regardless of target_gas_ratio and releases nonces of possibly in-flight transactions on any send error.

This branch keeps the 16.7M limit and derives the batch size from the fee model's cost per state byte instead, so the transactions stay valid on both fork states without any retry logic:

cost per state byte addresses per tx
0 (--pre-amsterdam-fee-model) 370 (unchanged)
1530 (Amsterdam default) 68

Because the on-chain price is dynamic and can exceed the static estimate, the batch shrinks by a quarter whenever a bloat tx still runs out of gas and grows back slowly after ten clean rounds. Nonces of transactions built for a round that is abandoned before sending are released so wallets do not develop a permanent gap.

Testing

  • go fmt, go vet, staticcheck (no findings in touched files) and the full test suite pass.
  • New tests for the daemon lock release and the OnComplete contract drive the real code paths and fail against the previous code.
  • The erc20_bloater sizing is unit-tested but not yet validated on a Glamsterdam devnet.

SendMultiTransactionBatch drains a wallet's size-1 error channel at most
once before cancelling the batch. Every further sub-goroutine that failed
blocked forever on its send, leaking the goroutine and its semaphore slot.
Signal best-effort instead; the error is still recorded per transaction.
The confirmation path updated pendingTxCount with a load-then-store under
txNonceMutex while GetNextNonce increments it under nonceMutex. A store
computed from a stale load could roll the counter back and hand out an
in-flight nonce twice.
The non-batcher funding path never recorded its transfers in batchTxMap,
so the shared credit loop skipped them and the child wallets' tracked
balance stayed stale after a successful transfer.
DeleteSpammer held the map write lock across Pause, which waits up to 10s
for the scenario to wind down, freezing every reader meanwhile. Release
the lock around Pause like DeleteGroup does and recheck the entry after
reacquiring it.
OnComplete is documented as always being called, and ReclaimFunds relies
on it to release its wait group. The early return for an already
cancelled context skipped the callback, leaving the reclaim (and the
spammer shutdown around it) hung forever.
Under EIP-8037 every fresh storage slot is charged 64 bytes of state
creation gas on top of the SSTORE cost. A transaction at or below the
EIP-7825 cap gets no state-gas reservoir, so that cost spills into
regular gas and the fixed 370-address batch ran out of gas on every
Amsterdam chain.

Derive the batch size from the fee model's cost per state byte while
keeping the gas limit at the EIP-7825 cap, so the transactions stay valid
on chains that have not activated Amsterdam yet. The batch shrinks when a
bloat tx still runs out of gas (the on-chain price can exceed the static
estimate) and grows back after successful rounds. Nonces of transactions
built for a round that is abandoned before sending are released.
@redpandabot

This comment has been minimized.

SetNonce raised pendingTxCount with a load-then-store under nonceMutex,
which does not exclude the confirmation path's update under txNonceMutex.
A confirmation landing between its load and store could be overwritten
with the lower on-chain nonce, reopening the clobber the previous commit
closed. The root wallet resyncs its nonce every 48s, so this is reachable
in normal operation.
@redpandabot

This comment has been minimized.

A hard error from SendMultiTransactionBatch left the nonces allocated by
buildBloatTx permanently skipped when the tx never reached a node, so the
next round built that wallet's tx at nonce+1 and could never get it
included. A submission failure drops the tx from the wallet's pending
tracking while a submitted-but-unconfirmed tx stays there, so use that to
release only the nonces that are actually free. Also treat a nil receipt
as a failed round instead of dereferencing it.

@redpandabot redpandabot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer branch combining six contributor bug fixes: best-effort error signalling to stop the batch goroutine leak, a monotonic CAS for the pending nonce counter, funding credit for the non-batcher path, releasing the daemon spammer-map lock around Pause (with a post-reacquire recheck), calling OnComplete on an already-cancelled submission, and deriving erc20_bloater batch sizes from state-creation cost so bloat txs stay under the fixed gas limit on both pre-Amsterdam and Amsterdam chains. I traced every exit path (locks, channels, nonce tracking) and found the fixes sound: the first batch error still reaches the manager, OnComplete fires exactly once with a nil-guarded receipt, the CAS never moves pendingTxCount backwards, and the erc20 nonce-release never reuses an in-flight nonce.


Reviewed 11 changed file(s) @ 7a56f71e — no blocking issues found.
"I'm not a great programmer; I'm just a good programmer with great habits." — Kent Beck

@pk910
pk910 merged commit 74e0a6f into master Sep 11, 2026
7 checks passed
@pk910
pk910 deleted the pk910/combined-fixes branch September 11, 2026 05:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] erc20_bloater: bloat transactions revert with out-of-gas on Amsterdam (EIP-8037)

1 participant